home *** CD-ROM | disk | FTP | other *** search
- /*
- Find multiple copies of the same file on a single disk
- drive. Compiled under Microsoft C 6.0 using:
- cl /Fs /W4 /Ox /AC no_dup.c
- Compiles without modifications undder TURBO C integrated
- environment.
- In both cases requires compact memory model libraries.
- */
-
- #include "no_dup.h"
-
- Flag first_call = True;
-
- GlobalOpt globalopt = { False, False, 0, 0L };
-
- int main( int argc, char **argv )
- {
- DirEntry *current_file, *next_file;
- DirList *path, *root, *new_path;
- char current_path[MAX_PATH], file_spec[MAX_FLEN];
- PtrList *ptrbase, *ptrlist;
- Flag duplicate = False;
-
- for( ; argc > 1; argc-- )
- {
- if(argv[argc-1][1] == 'f' || argv[argc-1][1] == 'F')
- globalopt.file = True;
- else if( argv[argc-1][1] == 'd'
- || argv[argc-1][1] == 'D' )
- globalopt.dir = True;
- else
- fprintf( stderr,
- "Invalid command line switch: %s\n",
- argv[argc-1] );
- }
-
- strcpy( file_spec, "*.*" );
- current_file = NULL;
- (void) getcwd( current_path, MAX_PATH );
- fprintf( stderr, "%s\n", VERSION );
- printf( "Processing %s\n", current_path );
- path = make_path( current_path, "", NULL );
- new_path = root = path;
- if( (ptrbase = malloc( sizeof( PtrList ) * MAX_FILES ))
- == NULL )
- {
- fprintf( stderr, "Insufficient near memory.\n" );
- exit( EXIT_FAILURE );
- }
- ptrlist = ptrbase;
-
- while( (path = get_path( root ) ) != NULL )
- {
- strcpy( current_path, path->pathname );
- strcat( current_path, file_spec );
- first_call = True;
-
- while( (current_file = get_direntry(current_path))
- != NULL )
- {
- current_file->path = path->pathname;
- if( current_file->attrib & FA_DIREC )
- {
- new_path = make_path( path->pathname,
- current_file->name, new_path );
- }
- else
- {
- ++globalopt.file_count;
- globalopt.total_file_size
- += current_file->size;
- if( globalopt.file_count == MAX_FILES )
- {
- fprintf( stderr,
- "Too many files\n"
- "Program is limited to %u files.\n",
- MAX_FILES );
- exit( EXIT_FAILURE );
- }
- *ptrlist = ( char * ) current_file;
- ++ptrlist;
- }
- }
- path->dir_processed = True;
- }
- *ptrlist = NULL;
- printf( "Processed %d files occupying %lu bytes.\n",
- globalopt.file_count,
- globalopt.total_file_size );
-
- qsort( (void *) ptrbase,
- (size_t) globalopt.file_count,
- (size_t) sizeof( PtrList ), name_comp );
-
- if( globalopt.file ) /* optionally list files */
- {
- printf( SEPARATOR );
- printf( "Listing of all files below %s\n",root);
- for( ptrlist = ptrbase; *ptrlist; ptrlist++ )
- fprint_direntry( stdout,
- (DirEntry *) *ptrlist );
- }
-
- printf( SEPARATOR );
- printf( "Duplicate files below %s\n", root );
- for( ptrlist = ptrbase, duplicate = False;
- *ptrlist; ptrlist++ )
- {
- current_file = ( DirEntry * ) *ptrlist;
- next_file = ( DirEntry * ) *(ptrlist+1);
- if( !strcmp(current_file->name,next_file->name))
- {
- duplicate = True;
- fprint_direntry( stdout, current_file );
- }
- else if( duplicate == True )
- {
- /* print the last file in a group */
- /* otherwise we'll miss it */
- current_file = ( DirEntry * ) *ptrlist;
- fprint_direntry( stdout, current_file );
- printf( SEPARATOR );
- duplicate = False;
- }
- }
-
- return EXIT_SUCCESS;
- }
-
- /*
- get file info from DOS directory and allocate memory
- */
- DirEntry *get_direntry( char *path )
- {
- static struct ffblk file_info;
- DirEntry *new_entry;
-
- if( first_call == True )
- {
- if( findfirst( path, &file_info, FA_DIREC ) )
- return NULL;
- first_call = False;
- }
- else
- {
- if( findnext( &file_info ) )
- {
- return NULL;
- }
- }
- if( (new_entry = malloc(sizeof(DirEntry))) == NULL )
- {
- fprintf( stderr, "Insufficient far memory.\n" );
- exit( EXIT_FAILURE );
- }
-
- strcpy( new_entry->name, file_info.ff_name );
- new_entry->attrib = file_info.ff_attrib;
- if( new_entry->attrib & FA_DIREC )
- new_entry->dir_processed = False;
- new_entry->time = file_info.ff_ftime;
- new_entry->date = file_info.ff_fdate;
- new_entry->size = file_info.ff_fsize;
-
- return new_entry;
- }
-
- /*
- build a directory path by appending subdir to basedir
- */
- DirList *make_path( char *basedir, char *subdir,
- DirList *prev )
- {
- DirList *new_dir;
-
- if( (new_dir = malloc( sizeof( DirList ) ) ) == NULL )
- {
- fprintf( stderr, "Insufficient near memory.\n" );
- exit( EXIT_FAILURE );
- }
- strcpy( new_dir->pathname, basedir );
- strcat( new_dir->pathname, subdir );
- if( *(new_dir->pathname + strlen(new_dir->pathname) - 1)
- != '\\' )
- strcat( new_dir->pathname, "\\" );
- if( strcmp( subdir, "." ) && strcmp( subdir, ".." ) )
- {
- /* only "real" directories meet the condition */
- new_dir->dir_processed = False;
- if( globalopt.dir )
- printf( "Directory:%s\n", new_dir->pathname );
- }
- else
- new_dir->dir_processed = True;
- if( prev )
- {
- new_dir->prev = prev;
- new_dir->next = NULL;
- prev->next = new_dir;
- }
- else
- {
- new_dir->prev = NULL;
- new_dir->next = NULL;
- }
-
- return new_dir;
- }
-
- /*
- find an unprocessed directory
- */
- DirList *get_path( DirList *root )
- {
- DirList *path;
-
- path = root;
- while( path->next && (path->dir_processed == True) )
- {
- path = path->next;
- }
- if( path->dir_processed == True)
- return NULL;
- else
- return path;
- }
-
- /*
- DirEntry comparison function
- */
- int name_comp( const void *p1, const void *p2 )
- {
- PtrList *ptr1, *ptr2;
- DirEntry *f1, *f2;
- int status;
-
- ptr1 = (PtrList *) p1;
- ptr2 = (PtrList *) p2;
- f1 = (DirEntry *) *ptr1;
- f2 = (DirEntry *) *ptr2;
-
- if( status = strcmp( f1->name, f2->name ) )
- return( status );
- else if( status = f1->date - f2->date )
- return( status );
- else if( status = f1->time - f2->time )
- return( status );
- else
- return( strcmp( f1->path, f2->path ) );
- }
-
- /*
- print file information to the ouptut stream
- */
- void fprint_direntry( FILE *fout, DirEntry *current_file )
- {
- char date_buf[10], time_buf[10];
-
- fprintf( fout, "%-14s %6ld %c%c %s %s %s\n",
- current_file->name,
- current_file->size,
- (current_file->attrib & FA_RDONLY ) ? 'R' : '.',
- (current_file->attrib & FA_ARCH ) ? 'A' : '.',
- datestr( current_file->date, date_buf ),
- timestr( current_file->time, time_buf ),
- current_file->path );
- }
-
- /*
- The following functions are copied from QC 2.0 online
- help. These functions convert wr_time and wr_date into
- strings.
- */
- char *timestr( unsigned t, char *buf )
- {
- int h = (t >> 11) & 0x1f, m = (t >> 5) & 0x3f;
- sprintf( buf, "%2.2d:%02.2d", h, m );
- return buf;
- }
-
- char *datestr( unsigned d, char *buf )
- {
- sprintf( buf, "%2.2d/%02.2d/%02.2d",
- (d >> 5) & 0x0f, d & 0x1f, (d >> 9) + 80 );
- return buf;
- }
-